package com.hp.bon.sgw.wh.channel.handler;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.hp.bon.sgw.Constants;
import com.hp.bon.sgw.bean.XmlMessage;
import com.hp.bon.sgw.core.BuzProcessorManager;
import com.hp.bon.sgw.core.CallParam;
import com.hp.bon.sgw.core.channel.SoapChannel;
import com.hp.bon.sgw.core.channel.handler.IAsynCallHandler;
import com.hp.bon.sgw.threads.TaskManager;
import com.hp.bon.sgw.wh.service.UserResourceConfigService;
import com.hp.bon.sgw.wh.utils.LogUtil;
import com.hp.bon.sgw.wh.utils.ResultCodeUtil;
import com.hp.ocs.diameter.DiameterUtils;
import com.hp.ocs.diameter.message.*;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.simpleframework.http.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 费用查询接口
 * @author lwq
 *
 */
public class ReturnBalanceHandle implements IAsynCallHandler {
	
	private static final Logger _log = LoggerFactory.getLogger(ReturnBalanceHandle.class);
	private PrintStream printStream;
	private JSONObject jsonContent;
	private UserResourceConfigService userResourceConfigService ;
    private long startTime;
    private Request request;
	public ReturnBalanceHandle(PrintStream printStream, JSONObject jsonContent, Request request, long startTime) {
		this.printStream = printStream;
		this.jsonContent = jsonContent;
        this.startTime = startTime;
        this.request = request;
	}

	@Override
	public int getProtocolType() {
		return 0;
	}

	@Override
	public void onCallResult(CallParam callParam) {
		XmlMessage ack = null;
		Object response = null;
		if (callParam.getResponse() != null) {
			response = callParam.getResponse();
		} else if (callParam.getRecvResponse() != null) {
			response = callParam.getRecvResponse();
		}
		if (response == null) {
			int _retcodeTmp = callParam.getRetCode() == 3002 ? 11202 : callParam.getRetCode();
			ack = SoapChannel.createERRAnwser(callParam.getSessionId(), _retcodeTmp, callParam.getResultMsg());
			callParam.setServiceResultCode(_retcodeTmp);// 11203
		} else {
			if (response instanceof Message) {// CCA -> XML
                _log.info("================response instanceof Message");
                ack = BuzProcessorManager.getInstance().convertMessageToAck(callParam);
			} else if (response instanceof XmlMessage) {
                _log.info("================response instanceof XmlMessage");
                ack = (XmlMessage) response;
			} else {
				_log.warn("unknown response type:" + callParam.getResponse().getClass().getName());
			}
		}
		try {
			String respXML = convertResponseString((Message) response, callParam.getServiceResultCode());
			if("0".equals(respXML)) {
				return;
			}

			byte[] resp = respXML.getBytes("UTF-8");
			ack.setLength(resp.length);
			ack.setMsgTime(System.currentTimeMillis());
			printStream.write(resp);
			printStream.close();
			callParam.setResponse(ack);
//			if (callParam.getRetCode() == Constants.ResultCode.SUCCESS) {// 成功的消息，请求应答入库
//				MessageDetail detail = new MessageDetail();
//				detail.setBusinessCallId(callParam.getBussinessCallId());
//				detail.setSessionId(callParam.getSessionId());
//				detail.setServiceContextId(callParam.getServiceContextId());
//				detail.setMessageType(MessageType.WSA);
//				detail.setDetails(ack.getDATA());
//				detail.setMsgTime(new Date(ack.getMsgTime()));
//				detail.setOpType("send");
//				detail.setHostId(callParam.getUserName());
//				MessageDetailCacheManager.getInstance().add(detail);
//			}
            //记录到日志
            LogUtil.saveLogToABM(request,respXML,startTime);
			TaskManager.taskProcess(callParam);
            _log.info("http response(returnBalance) " + respXML);

		} catch (UnsupportedEncodingException e) {
			_log.info("convertResponseString UnsupportedEncodingException error,msg=" + e.getMessage());
		} catch (IOException e) {
			_log.info("convertResponseString IOException,msg=" + e.getMessage());
		}
	}

	
	
	/**
	 * 从Message中解析出需要的数据，并拼接成json字符串
	 * @param answer
	 * @param serviceResultCode
	 * @return
	 */
	private String convertResponseString(Message answer, int serviceResultCode) {
		Gson gson = new Gson();
		_log.info("ReturnBalanceHandle serviceResultCode = {}", serviceResultCode);
        _log.info("===========service_result_code===============" + serviceResultCode);

        // 返回json字符串最外层的map
		Map<String, Object> data = new HashMap<String, Object>();
		// json字符串中的ReturnPlanInfo节点，该节点为list
		List<Map<String, Object>> returnPlanInfoList = new ArrayList<Map<String, Object>>();
		
		if(11202 == serviceResultCode || answer == null ) {
			data.put("resultCode", "-1");
			data.put("resultMsg", "查询失败");
            String newCode = ResultCodeUtil.updateResultCode(data.get("resultCode"), userResourceConfigService.getValue("api_resultCode"), userResourceConfigService.getValue("api_defaultResult"));
            data.put("resultCode", newCode);
			return gson.toJson(data);
		}
		// 从下游解析返回信息中解析出来的数据，该数据和用户需要的数据并不相符，需要进行处理
		Map<String, Object> avpResultMap = getAvpsFromMessage(answer);
		
		if (null == avpResultMap) {
			data.put("resultCode", "-1");
			data.put("resultMsg", "查询失败");
		}else if (serviceResultCode == 0) {
			String jf3_flag=userResourceConfigService.getValue("jf3_flag", "0");
			if("1".equals(jf3_flag)) {
			    _log.info("=================进入新流程数据解析=================");
				//新的接口解析
				String Latn_Id = null;
				String Area_Code = null;
			    AVP avp = answer.find(Constants.DIAMETER_AVP_SERVICE_INFOMATION,Constants.DIAMETER_VENDOR_3GPP);
			    AVP_Grouped avpServiceInfomation;
				try {
					avpServiceInfomation = new AVP_Grouped(avp);
				    AVP avpBillSerialNbr = avpServiceInfomation.find(80411,Constants.DIAMETER_VENDOR_CT);
				    if (avpBillSerialNbr != null){
				    	Latn_Id = new AVP_UTF8String(avpBillSerialNbr).queryValue();
				    }
				    AVP avpBillSerialNbr2 = avpServiceInfomation.find(50207,Constants.DIAMETER_VENDOR_CT);
				    if (avpBillSerialNbr2 != null){
				    	Area_Code = new AVP_UTF8String(avpBillSerialNbr2).queryValue();
				    }
					
				} catch (InvalidAVPLengthException e) {
					_log.error(" get  Latn_Id  getAvpsFromMessage is error when Ne response cca message");
				}
				String versionType = getVersionType(Latn_Id, "0");//传参0 1001类 传1 84210类   返参 1 新 0 旧的
				String objType = jsonContent.getJSONObject("svcObjectStruct").getString("objType");
				String objValue = jsonContent.getJSONObject("svcObjectStruct").getString("objValue");
				String objAttr = jsonContent.getJSONObject("svcObjectStruct").getString("objAttr");
				String dataArea = jsonContent.getJSONObject("svcObjectStruct").getString("dataArea");
				Element serviceInformation = null;
				if("1".equals(versionType)) {
					//开关开,调用新流程
                    _log.info("=================进入新流程中的 新流程=================");
					serviceInformation = DocumentHelper.createElement("Service_Information");
					serviceInformation.addElement("Channel_Id").setText("200");
					serviceInformation.addElement("Area_Code").setText(Area_Code);
					serviceInformation.addElement("DestinationAttr").setText(objAttr);
					serviceInformation.addElement("Destination_Id").setText(objValue);
					serviceInformation.addElement("Destination_Id_Type").setText("2");
					serviceInformation.addElement("Latn_Id").setText(Latn_Id);
					serviceInformation.addElement("Query_Flag").setText(dataArea.equals("2")?"1":"0");
				}else {
                    _log.info("=================进入新流程中的 旧流程=================");
					//开关 关,旧流程
					serviceInformation = DocumentHelper.createElement("Service_Information");
					Element balanceInformation = serviceInformation.addElement("Balance_Information");
					// 用户号码(如果是用户号码且用户属性为固话、宽带时，,此AVP取值要求带区号,含0
					balanceInformation.addElement("Destination_Id").setText(jsonContent.getJSONObject("svcObjectStruct").getString("objValue"));
					// 用户号码类型：2-用户号码
					balanceInformation.addElement("Destination_Id_Type").setText("2");
					// 用户属性（当号码类型为用户号码时填写）0-固话、1-、2-移动、3-宽带、4-智能公话、5-互联星空、6-天翼高清、99-未知
					balanceInformation.addElement("DestinationAttr").setText(objAttr);
					// 电话区号
					if (!objValue.startsWith("0") || objValue.startsWith("027")) {
						Area_Code = "027";
					} else {
						Area_Code = objValue.substring(0, 4);
					}
					balanceInformation.addElement("Area_Code").setText(Area_Code);
					// 查询业务类型（默认0）：0按帐户查询、1按用户查询
					balanceInformation.addElement("Query_Flag").setText(dataArea.equals("2")?"1":"0");
					// 省内和集团方向区分标示，省内填默认值1
					balanceInformation.addElement("QueryType").setText("1");
				}
				
				XmlMessage req = new XmlMessage(true);
				String tmallHostId = "SGWHBCFQ@027.ctnbc-bon.net";
				String sessionId = DiameterUtils.makeSessionID(tmallHostId);
				req.setIp(jsonContent.getString("IP"));
				req.setMsgTime(System.currentTimeMillis());
				req.setMID(sessionId);
				req.setUID(tmallHostId);
				req.setSCID("1".equals(versionType) ? "ReturnBalance.jf3@027.ctnbc-bon.net" : "ReturnBalance.balanceYXHB9@027.ctnbc-bon.net");
				req.setSIG(null);
				req.setREPTAG(0);
				req.setDATA(serviceInformation.asXML());
				req.setDataElement(serviceInformation);
				// new CallParam对象
				ReturnBalanceHandle2 returnBalanceHandle = new ReturnBalanceHandle2(printStream,jsonContent,request,startTime);
				CallParam callParam = new CallParam(req.getMID(), req.getSCID(), req, req.getUID(), returnBalanceHandle);
				BuzProcessorManager.getInstance().processRequest(callParam);
				
				return "0";
			}
            _log.info("=================进入旧流程数据解析=================");
			List<Map<String, Object>> list = (List<Map<String, Object>>)avpResultMap.get("ReturnPlanInfos");
			for(Map<String, Object> one : list){
				Map<String, Object> map = new HashMap<String, Object>();
				map.put("returnPlanId", Long.valueOf((String)one.get("ReturnPlanId")));
				map.put("returnPlanName", one.get("ReturnPlanName"));
				map.put("stateDate", one.get("StateDate"));
				map.put("startTime", one.get("StartTime"));
				map.put("endTime", one.get("End_Time"));
				map.put("state", one.get("State"));
				map.put("returnFlag", one.get(""));
				map.put("returnSumMonth", Long.valueOf((String)one.get("ReturnSumMonth")));
				map.put("returnSumBalance", Long.valueOf((String)one.get("ReturnSumBalance")));
				map.put("returnMonth", Long.valueOf((String)one.get("ReturnMonth")));
				map.put("returnBalance", Long.valueOf((String)one.get("ReturnBalance")));
				map.put("paymentMethod", Long.valueOf((String)one.get("Payment_Method")));
				map.put("accNbrDetail", one.get(""));
				returnPlanInfoList.add(map);
			}
			data.put("resultCode", "0");
			data.put("resultMsg", "SUCCESS");
			data.put("returnPlanInfo", returnPlanInfoList);
		}else {
			data.put("resultCode", serviceResultCode);
			data.put("resultMsg", "查询失败");
		}
        String newCode = ResultCodeUtil.updateResultCode(data.get("resultCode"), userResourceConfigService.getValue("api_resultCode"), userResourceConfigService.getValue("api_defaultResult"));
        data.put("resultCode", newCode);
		return gson.toJson(data);
	}

	
	
	/**
	 * 从返回信息中解析AVP信息
	 * @param answer
	 * @return
	 */
	public Map<String, Object> getAvpsFromMessage(Message answer) {
		Map<String, Object> resultMap = new HashMap<String, Object>();
		List<Map<String, Object>> returnPlanInfos = new ArrayList<Map<String, Object>>();
		try {
			AVP serviceINformationAVP = answer.find(Constants.DIAMETER_AVP_SERVICE_INFOMATION, Constants.DIAMETER_VENDOR_3GPP);
			AVP_Grouped serviceInfomationGroup;
			serviceInfomationGroup = new AVP_Grouped(serviceINformationAVP);
			AVP[] avps = serviceInfomationGroup.queryAVPs();
			for(AVP avp : avps){
				if(avp.code() == 20631 && avp.vendorID() == 81000){
					// Result节点
					resultMap.put("Result", String.valueOf(new AVP_Unsigned32(avp).queryValue()));
				}else if(avp.code() == 90207 && avp.vendorID() == 81000){
					// ReturnPlanInfo节点，下游返回信息中会有多个该节点
					Map<String, Object> map = new HashMap<String, Object>();
					map.put("ReturnPlanId", "");
					map.put("ReturnPlanName", "");
					map.put("StateDate", "");
					map.put("StartTime", "");
					map.put("End_Time", "");
					map.put("State", "");
					map.put("ReturnSumMonth", "");
					map.put("ReturnSumBalance", "");
					map.put("ReturnMonth", "");
					map.put("ReturnBalance", "");
					map.put("Payment_Method", "");
					map.put("BalanceTypeFlag", "");
					map.put("AccNbrDetail", "");
					// 返还计划实例ID
					AVP_Grouped returnPlanInfoGroup = new AVP_Grouped(avp);
					AVP ReturnPlanId = returnPlanInfoGroup.find(90204, Constants.DIAMETER_VENDOR_CT);
					if (ReturnPlanId != null) {
						map.put("ReturnPlanId", new AVP_UTF8String(ReturnPlanId).queryValue());
					}
					// 返还计划名称
					AVP ReturnPlanName = returnPlanInfoGroup.find(90206, Constants.DIAMETER_VENDOR_CT);
					if (ReturnPlanName != null) {
						map.put("ReturnPlanName", new AVP_UTF8String(ReturnPlanName).queryValue());
					}
					// 状态时间
					AVP StateDate = returnPlanInfoGroup.find(80419, Constants.DIAMETER_VENDOR_CT);
					if (StateDate != null) {
						map.put("StateDate", new AVP_UTF8String(StateDate).queryValue());
					}
					// 生效时间
					AVP StartTime = returnPlanInfoGroup.find(5073, Constants.DIAMETER_VENDOR_CT);
					if (StartTime != null) {
						map.put("StartTime", new AVP_UTF8String(StartTime).queryValue());
					}
					// 失效时间
					AVP End_Time = returnPlanInfoGroup.find(5075, Constants.DIAMETER_VENDOR_CT);
					if (End_Time != null) {
						map.put("End_Time", new AVP_UTF8String(End_Time).queryValue());
					}
					// 状态：00A有效、00X 失效
					AVP State = returnPlanInfoGroup.find(82013, Constants.DIAMETER_VENDOR_CT);
					if (State != null) {
						map.put("State", new AVP_UTF8String(State).queryValue());
					}
					// 累积返还月数
					AVP ReturnSumMonth = returnPlanInfoGroup.find(90209, Constants.DIAMETER_VENDOR_CT);
					if (ReturnSumMonth != null) {
						map.put("ReturnSumMonth", new AVP_UTF8String(ReturnSumMonth).queryValue());
					}
					// 累积返金额
					AVP ReturnSumBalance = returnPlanInfoGroup.find(90210, Constants.DIAMETER_VENDOR_CT);
					if (ReturnSumBalance != null) {
						map.put("ReturnSumBalance", String.valueOf(new AVP_Integer32(ReturnSumBalance).queryValue()));
					}
					// 剩余未返还月数
					AVP ReturnMonth = returnPlanInfoGroup.find(90211, Constants.DIAMETER_VENDOR_CT);
					if (ReturnMonth != null) {
						map.put("ReturnMonth", new AVP_UTF8String(ReturnMonth).queryValue());
					}
					// 剩余未返金额
					AVP ReturnBalance = returnPlanInfoGroup.find(90212, Constants.DIAMETER_VENDOR_CT);
					if (ReturnBalance != null) {
						map.put("ReturnBalance", String.valueOf(new AVP_Integer32(ReturnBalance).queryValue()));
					}
					// 付款方式：11现金、12支票、13信用卡缴费、14代缴、15充值、16套餐促销（预存、返还、赠送）费用
					AVP Payment_Method = returnPlanInfoGroup.find(80129, Constants.DIAMETER_VENDOR_CT);
					if (Payment_Method != null) {
						map.put("Payment_Method", String.valueOf(new AVP_Integer32(Payment_Method).queryValue()));
					}
					// 余额类型标识：0通用余额、1专用余额
					AVP BalanceTypeFlag = returnPlanInfoGroup.find(90208, Constants.DIAMETER_VENDOR_CT);
					if (BalanceTypeFlag != null) {
						map.put("BalanceTypeFlag", String.valueOf(new AVP_Integer32(BalanceTypeFlag).queryValue()));
					}
					// 号码信息描述
					AVP AccNbrDetail = returnPlanInfoGroup.find(90226, Constants.DIAMETER_VENDOR_CT);
					if (AccNbrDetail != null) {
						map.put("AccNbrDetail", new AVP_UTF8String(AccNbrDetail).queryValue());
					}
					returnPlanInfos.add(map);
					
					
				}
			}
			resultMap.put("ReturnPlanInfos", returnPlanInfos);
			
		} catch (InvalidAVPLengthException e) {
			resultMap = null;
			_log.error("getAvpsFromMessage is error：", e);
		}
		return resultMap;
	}
	/**
	 * 由于计费侧提供的接口协议没变，只是地址调整，割接到3.0的本地网需要调用新的地址
	 * 集团电子发票API接口调整
	 * 获取判断使用的地址
	 * jf3_flag 刷新开关  配置为1则表示启用割接地市判断，配置为0则表示按现有的流程
	 * Jf3_jt_latn_id  割接地市配置项（多个地市用逗号分隔，如果配置项调整为888，则表示全部调用新地址）
	 * resultLanIdStr 区域编码
	 * cityId
	 * jf3_jt_latn_id 是84201这种
		jf3_latn_id是1001 1018 这种
		jf3_area_coee是027 0716 这种
		type 传参0 1001类 传1 84210类   返参 1 新 0 旧的
	 */
	private String getVersionType(String cityId,String type) {
		String jf3_flag = userResourceConfigService.getValue("jf3_flag","");////增加刷新开关  ,配置为1则表示启用割接地市判断，配置为0则表示按现有的流程
		String jf3_jt_latn_id = userResourceConfigService.getValue("jf3_jt_latn_id","");
		String jf3_latn_id = userResourceConfigService.getValue("jf3_latn_id","");
		String str;
		if("0".equals(type)) {
			//1001类型
			str = jf3_latn_id;
		}else {
			//84201 类型
			str = jf3_jt_latn_id;
		}
		//1 新流程  0 旧的流程
		if("1".equals(jf3_flag)) {
			if("888".equals(str)) {
				return "1";//新的
			}else {
				String[] split_jt_latn_id = str.split(",");
				for (String string : split_jt_latn_id) {
					if(string.equals(cityId)) {
						//包含,仅区分新旧
						return "1";//新的 Recharged.jf3@027.ctnbc-bon.net
					}
				}
			}
			
		}
		return "0";//旧的 SeverRecharge.SGWPAY@027.ctnbc-bon.net  
	}
	public static void main(String[] args) {
		try {
			SimpleDateFormat sdf=new SimpleDateFormat("yyyyMM");
			Date parse = sdf.parse("2019");
			System.out.println(parse.getYear());
		}catch (Exception e) {
			e.printStackTrace();
		}
		
	}

}
